//#############################################################################################
/**
 * 해당날짜의 포맷팅된 문자열을 리턴하는 함수이다.
 * @param f 날짜포맷
 */
Date.prototype.format = function(f) {
    if (!this.valueOf()) return " "; 
    var weekName = ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일"];
    var d = this;
     
    return f.replace(/(yyyy|yy|MM|dd|E|hh|mm|ss|a\/p)/gi, function($1) {
        switch ($1) {
            case "yyyy": return d.getFullYear();
            case "yy": return (d.getFullYear() % 1000).zf(2);
            case "MM": return (d.getMonth() + 1).zf(2);
            case "dd": return d.getDate().zf(2);
            case "E": return weekName[d.getDay()];
            case "HH": return d.getHours().zf(2);
            case "hh": return ((h = d.getHours() % 12) ? h : 12).zf(2);
            case "mm": return d.getMinutes().zf(2);
            case "ss": return d.getSeconds().zf(2);
            case "a/p": return d.getHours() < 12 ? "오전" : "오후";
            default: return $1;
        }
    });
};

String.prototype.string = function(len){var s = '', i = 0; while (i++ < len) { s += this; } return s;};
String.prototype.zf = function(len){return "0".string(len - this.length) + this;};
Number.prototype.zf = function(len){return this.toString().zf(len);};

//2011년 09월 11일 오후 03시 45분 42초
//console.log(new Date().format("yyyy년 MM월 dd일 a/p hh시 mm분 ss초"));
 
//2014/02/05 11:16:31
//console.log(new Date().format("yyyy/MM/dd HH:mm:ss"));

//2011-09-11
//console.log(new Date().format("yyyy-MM-dd"));
 
//'11 09.11
//console.log(new Date().format("'yy MM.dd"));
 
//2011-09-11 일요일
//console.log(new Date().format("yyyy-MM-dd E"));
 
//현재년도 : 2011
//console.log("현재년도 : " + new Date().format("yyyy"));

/**
 * 포맷팅된 문자열을 리턴하는 함수이다.
 * @param 
 */
var formatStr = function() {
    // The string containing the format items (e.g. "{0}")
    // will and always has to be the first argument.
    var theString = arguments[0];
    
    // start with the second argument (i = 1)
    for (var i = 1; i < arguments.length; i++) {
        // "gm" = RegEx options for Global search (more than one instance)
        // and for Multiline search
        var regEx = new RegExp("\\{" + (i - 1) + "\\}", "gm");
        theString = theString.replace(regEx, arguments[i]);
    }
    
    return theString;
};
// ex) String.format("{0}+{1}+{2}", "11","22","33");


//#############################################################################################

/**
 * 해당 문자열의 바이트를 갖어오는 함수이다.
 */
function getByte(s) {
    var sum = 0;
    var len = s.length;
    for (var i = 0; i < len; i++) {
        var ch = s.substring(i, i + 1);
        var en = escape(ch);
        if (en.length <= 4) {
            sum++;
        }
        else {
            sum += 2;
        }
    }
    return sum;
}

/**
 * 해당 문자열이 숫자인지 체크하는 함수이다.
 */

function checkNumber(str) {
    var flag = true;
    if (str.length > 0) {
        for (i = 0; i < str.length; i++) {
            if (str.charAt(i) < '0' || str.charAt(i) > '9') {
                flag = false;
            }
        }
    }
    return flag;
}

var DateUtil = {
    months:new Array('01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'),

    /**
     * 오늘 날짜를 리턴해준다.
     * format : yyyy-mm-dd
     */
    getToday:function(config) {
        var now = new Date();
        var date = ((now.getDate() < 10) ? "0" : "") + now.getDate();
        var today;

        if (!config.format) {
            today = (DateUtil.fourdigits(now.getYear())) + '-' + DateUtil.months[now.getMonth()] + "-" + date;
        }

        return today;
    },

    fourdigits:function(number) {
        return (number < 1000) ? number + 1900 : number;
    }
}

/**
 * 비동기 통신을 위한 기능들을 제공한다.
 * get과 post 함수를 따로 분리해 놓은 이유는 함수명으로 쉽게 알기 위해서 이다.
 */
var AjaxUtil = {

    /**
     * Get방식으로 호출한다.
     * 사용예)
     * var config = {
     *         url:'/test.do',                        //required
     *         data:'testId=001&testName=name',      //required
     *         async:false                          /optional
     *         success:succesFnc,                    //optional
     *         error:failFnc                        //optional
     * };
     * AjaxUtil.callGetWay(config);
     */
    callGetWay:function(config) {
    	
        $.ajax({
            type : "get",
            url : config.url,
            async: config.async || true,
            data : config.data,
            success : function(msg) {
                config.success ? config.success(msg) : '';
            },
            error:function(event, request, settings) {
                config.error ? config.error(event, request, settings) : '';
            }
        });
    },

    /**
     * Post방식으로 호출한다.
     * 사용예)
     * var config = {
     *         url:'/test.do',                        //required
     *         data:'testId=001&testName=name',    //required
     *         async:false                          /optional
     *         success:succesFnc,                    //optional
     *         error:failFnc                        //optional
     * };
     * AjaxUtil.callGetWay(config);
     */
    callPostWay:function(config) {    	
        $.ajax({
            type : "post",
            url : config.url,
            async: config.async || true,
            data : config.data,
            success : function(msg) {
                config.success ? config.success(msg) : '';
            },
            error:function(event, request, settings) {
                config.error ? config.error(event, request, settings) : '';
            }
        });
    }
};

/**
 * 각 필드에서 거쳐야할 검증에 대한 함수를 정의해 주세요.
 */
var Validation = {
	    /**
	     * 해당 문자열이 숫자인지 체크하는 함수이다.
	     * @param str 문자열
	     */
	    checkNumber:function(str) {
	        var flag = true;
	        if (str.length > 0) {
	            for (i = 0; i < str.length; i++) {
	                if (str.charAt(i) < '0' || str.charAt(i) > '9') {
	                    flag = false;
	                }
	            }
	        }
	        return flag;
	    },
	    checkNumberVal:function(str) {
	    	var flag = true;
	    	var temp_val = "";
	        if (str.length > 0) {
	            for (i = 0; i < str.length; i++) {
	                if (str.charAt(i) < '0' || str.charAt(i) > '9') {
	                    return temp_val;
	                }
	                temp_val += str.charAt(i);
	            }
	        }
	        return temp_val;
	    },

	    /**
	     * 숫자의 범위를 검사한다.
	     * @param val 검사값
	     * @param range 검사범위
	     */
	    checkNumberRange:function(val, range) {
	        if (val > range) {
	            return false;
	        }
	        return true;
	    },

	    /**
	     * 해당 문자열의 Bytes를 리턴한다.
	     * @param s 문자열
	     * @returns {Number}
	     */
	    getByte:function(s) {
	        var sum = 0;
	        var len = s.length;
	        for (var i = 0; i < len; i++) {
	            var ch = s.substring(i, i + 1);
	            var en = escape(ch);
	            if (en.length <= 4) {
	                sum++;
	            }
	            else {
	                sum += 2;
	            }
	        }
	        return sum;
	    },

	    /**
	     * 입력 값이 한글인지를 검사한다.
	     * @param val 검사값
	     */
	    
	    is_han_chk: function(this_s,type){
	    	 /*
	    	 type
	    	 -> 'c' : 초성 포함
	    	 -> 's' : 초성 포함 + 공백 포함
	    	 -> '' : 초성, 공백 무시
	    	 */
	    	 temp_value = this_s;
	    	 regexp = '';
	    	 repexp = '';
	    	 switch(type){
		    	  case 'c': regexp = /[^ㄱ-ㅎ가-힣]/g;break;
		    	  case 's': regexp = /[^ㄱ-ㅎ가-힣]/g;break;
		    	  case '': regexp = /[^가-힣]/g; break;
		    	  default : regexp = /[^ㄱ-ㅎ가-힣s]/g;
	    	 }
	    	 if(regexp.test(temp_value))
	    	 {
	    		 return false;
	    	 }
	    	 return true;
	    },
	    
	    han_chk: function(this_s,type){
	   	 /*
	   	 type
	   	 -> 'c' : 초성 포함
	   	 -> 's' : 초성 포함 + 공백 포함
	   	 -> '' : 초성, 공백 무시
	   	 */
	   	 temp_value = this_s;
	   	 regexp = '';
	   	 repexp = '';
	   	 switch(type){
		    	  case 'c': regexp = /[^ㄱ-ㅎ가-힣]/g;break;
		    	  case 's': regexp = /[^ㄱ-ㅎ가-힣s]/g;break;
		    	  case '': regexp = /[^가-힣]/g; break;
		    	  default : regexp = /[^ㄱ-ㅎ가-힣s]/g;
	   	 }
	   	 if(regexp.test(temp_value))
	   	 {
	   		 temp_value = temp_value.replace(regexp,repexp);
	   		 return temp_value;
	   	 }
	   },


	    /**
	     * 입력 값이 유효한 이메일 형식인지를 검사한다.
	     * @param val 검사값
	     */
	    email_chk:function(val) {
	        if (val.length > 0) {
	            var regExp = /[a-z0-9]{2,}@[a-z0-9-]{2,}\.[a-z0-9]{2,}/i;

	            if (!regExp.test(val)) {
	                return false;
	            }
	        }else if(val == ''){
	            return false;
	        }

	        return true;
	    },
	    
	    /**
	     * 글입력제한
	     * @param n
	     * @param t
	     * @returns
	     */
	    limitChar:function(n,t){
	    	var length = getByte(t);
	      	if (length > n) {
	      		return true;
	      	}
	      	return false;
	    },
	    
	    /**
	     * n 까지 문자열 자르기
	     * @param v ->문자열
	     * @param m -> 길이
	     * @returns {String}
	     */
	    cutByteChar:function(v, m){
	    	var s;
	    	var r = ""; 
	    	var n = 0;
	    	for(var i=0;i<v.length;i++) { 
	    	  	s = escape(v.charAt(i));
	    	  	if(s.length>3) n++; 
	    	  	n++;
	    	  
	    	  	if(n<=m){
	    			r += unescape(s);
	    		}else{
	    			break;
	    		}
	    	} 
	    	return r;
	    }
	};

/**
 * 메시지가 나타났다 사라진다.
 */
var Notification = {
    /**
     * 통지를 한다.
     * 사용예)
     * var config = {
     *        txt:'내용',                     //required
     *        time:'1000',                    //optional
     *        callBackFnc:callbackFnc,        //optional
     * };
     * Notification.animationNoti(config);
     * @param config
     */
    animationNoti:function(config) {
        var id = new Date().getTime();
        var jId = '#'+id;

        var animNotiTag = '<div id="'+id+'" style="background-color:red;display:none;width:200px;height:100px">';
        animNotiTag += '</div>';
        $('body').append(animNotiTag);

        $(jId).html(config.txt);
        Notification.animNotiPosition($(jId));

        $(jId).animate({
            opacity: 0.0
        }, config.time || 3000, function() {
            $(this).remove();
            config.callBackFnc ? config.callBackFnc : '';
        });
    },

    /**
     * 통지의 포지션을 셋팅한다.
     * @param $animNoti 통지 jQuery객체
     */
    animNotiPosition:function($animNoti) {
        var top = $(document).height() / 2 - $animNoti.height() / 2;
        var left = $(document).width() / 2 - $animNoti.width() / 2;
        $animNoti.css({'position':'absolute', 'top':top + 'px','left':left + 'px','display':'block'});
    }
}
/**
 * 모달 기능의 창을 생성해주는 함수이다.
 * 예)alert, prompt, confirm
 */
var ModalDialog = {
    maskColor : '#000',
    maskOpacity : 0.5,
    maskLoadSpeed : 200,

    /**
     * alert과 같은 기능이다.
     * 사용예)
     * var config = {
     *         title:'warning',                //optional (default : Warning)
     *        content:'warning_content',         //required
     *        onBeforeLoad:function(){},        //optional
     *        onLoad:function(){},            //optional
     *        onBeforeClose:function(){},        //optional
     *        onClose:function(){},            //optional
     * };
     * ModalDialog.alertDialog(config);
     * 인자가 없을경우 ModalDialog.alertDialog({}); 같이 처리
     * @param config
     */
    alertDialog:function(config) {
        config.title ? $("#alertMoal > .title:eq(0)").html(config.title) : '';
        config.content ? $('#alertMoal > .content:eq(0)').html(config.content) : '';

        $('#alertMoal').removeData("overlay");
        $('#alertMoal').overlay({
            top: ModalDialog.modalHeight('alertMoal'),
            mask: {
                color: ModalDialog.maskColor,
                loadSpeed: ModalDialog.maskLoadSpeed,
                opacity: ModalDialog.maskOpacity
            },
            // disable this for modal dialog-type of overlays
            closeOnClick: false,
            load: true,
            onBeforeLoad:config.beforeLoad || null,
            onLoad:config.load || null,
            onBeforeClose:config.beforeClose || null,
            onClose:config.close || null
        });
    },

    /**
     * prompt와 같은 기능이다.
     * 사용예)
     * var config = {
     *         title:'warning',                //optional (default : Warning)
     *        content:'warning_content',         //required
     *        config.okFnc:'successFnc',        //required
     *        onBeforeLoad:function(){},        //optional
     *        onLoad:function(){},            //optional
     *        onBeforeClose:function(){},        //optional
     *        onClose:function(){},            //optional
     * };
     * ModalDialog.promptDialog(config);
     * @param config
     */
    promptDialog:function(config) {
        config.title ? $("#prompt > .title:eq(0)").html(config.title) : '';
        config.content ? $('#prompt > .content:eq(0)').html(config.content) : '';

        $('#prompt').contents().find('button:eq(0)').get(0).onclick = function() {
            var $inputObj = $('#prompt').contents().find('.promptInput:eq(0)');
            eval(config.okFnc + '("' + $inputObj.val() + '")');
            $inputObj.val('');
        };

        $('#prompt').contents().find('button:eq(1)').get(0).onclick = function() {
            $('#prompt').contents().find('.promptInput:eq(0)').val('');
        };

        $('#prompt').removeData("overlay");
        $('#prompt').overlay({
            top: ModalDialog.modalHeight('prompt'),

            mask: {
                color: ModalDialog.maskColor,
                loadSpeed: ModalDialog.maskLoadSpeed,
                opacity: ModalDialog.maskOpacity
            },
            // disable this for modal dialog-type of overlays
            closeOnClick: false,
            load: true,
            onBeforeLoad:config.beforeLoad || null,
            onLoad:config.load || null,
            onBeforeClose:config.beforeClose || null,
            onClose:config.close || null
        });
        $('#prompt').contents().find('.promptInput:eq(0)').focus();
    },

    /**
     * confirm과 같은 기능이다.
     * 사용예)
     * var config = {
     *         title:'warning',                //optional (default : Warning)
     *        content:'warning_content',         //required
     *        config.okFnc:'successFnc',        //optional
     *        config.failFnc:'failFnc',        //optional
     *        onBeforeLoad:function(){},        //optional
     *        onLoad:function(){},            //optional
     *        onBeforeClose:function(){},        //optional
     *        onClose:function(){},            //optional
     * };
     * ModalDialog.promptDialog(config);
     * @param config
     */
    confirmDialog:function(config) {
        config.title ? $("#confirm > .title:eq(0)").html(config.title) : '';
        config.content ? $('#confirm > .content:eq(0)').html(config.content) : '';

        $('#confirm').contents().find('button:eq(0)').get(0).onclick = function() {
            config.okFnc ? eval(config.okFnc + '()') : null;
        };

        $('#confirm').contents().find('button:eq(1)').get(0).onclick = function() {
            config.failFnc ? eval(config.failFnc + '()') : null;
        };

        $('#confirm').removeData("overlay");
        $('#confirm').overlay({
            top: ModalDialog.modalHeight('confirm'),
            mask: {
                color: ModalDialog.maskColor,
                loadSpeed: ModalDialog.maskLoadSpeed,
                opacity: ModalDialog.maskOpacity
            },
            // disable this for modal dialog-type of overlays
            closeOnClick: false,
            load: true,
            onBeforeLoad:config.beforeLoad || null,
            onLoad:config.load || null,
            onBeforeClose:config.beforeClose || null,
            onClose:config.close || null
        });
    },

    /**
     * Modal의 높이 위치값을 계산한다.
     * @param modalId
     * @returns {Number}
     */
    modalHeight:function(modalId) {
        return $(document).height() / 2 - $('#' + modalId).height() / 2;
    }
};

/**
 * List 페이지의 Display를 설정한다.
 */
var ListView = {
    /**
     * List의 row에 대한 이벤트를 설정해준다.
     * @param rowName TR태그의 class
     * 예)
     *  <tr class="testTr"></tr>
     *  <tr class="testTr"></tr>
     *  ListView.rowColorSetting('testTr');
     */
    rowColorSetting:function(rowClass) {
        $('.' + rowClass).bind('mouseover mouseout mousedown', function(event) {
            if (event.type == 'mouseover') {
                if (!$(this).data('click'))
                    $(this).css('background-color', '#F0FFFF');
            } else if (event.type == 'mouseout') {
                if (!$(this).data('click'))
                    $(this).css('background-color', '');
            } else {
                $('.' + rowClass).css('background-color', '');
                $('.' + rowClass).removeData('click');
                $(this).css('background-color', '#E0FFFF');
                $(this).data('click', true);
            }
        });
    }
};

var FileUtils = {
    searchImg:'/images/btn_file_search.gif',
    // 0:10MB, 1:5MB
    exeedFileSize:[10485760,5242880],

    /**
     * type="file"인 태그를 이미지로 변환하여 준다.
     */
    initFileUploads:function() {
//        var inputTag = '<input type="text" name="" class="i_text fileInput" style="width:250px"/>';
//        inputTag += '<img src="' + FileUtils.searchImg + '"/><br/>';

        var inputTag = '<div class="fakefile">';
        inputTag += '<input  type="file" class="fileInput"/>';
        inputTag += '<img src="' + FileUtils.searchImg + '" align="absmiddle"/>';
        inputTag += '</div>';

        $('.fileinputs').append(inputTag);

        $('.file').live('change mouseout', function(event) {
            if (navigator.appName == 'Microsoft Internet Explorer' && event.type == 'mouseout') {
                var preVal = $(this).data('preVal');
                if (this.value == '' || preVal == this.value) {
                    return false;
                }
                $(this).data('preVal', this.value);
                FileUtils.selectedFileName(this, formId);
            } else if (navigator.appName != 'Microsoft Internet Explorer' && event.type == 'change') {
                FileUtils.selectedFileName(this, formId);
            }
        });
    },

    /**
     * 선택한 파일이 중복이 되는지 여부를 검사하고 통과되면 input태그에 이름을 삽입한다.
     * @param obj type="file"인 객체
     * @param formId 폼아이디
     */
    selectedFileName:function(obj, formId) {
        var duplication = false;
        var fileVal = obj.value;

        $('*[name=files]').each(function(i) {
            if (obj != this) {
                if (fileVal == this.value)
                    duplication = true;
            }
        });

        if (duplication) {
            Notification.animationNoti({txt:'이미 추가된 파일입니다.'});
            $(obj).next().html('<input class="fileInput"/><img src="' + FileUtils.searchImg + '"/><span></span>');
            $(obj).replaceWith('<input type="file" class="file" name="files"/>');
        } else {
            fileVal = fileVal.replace(/\\/g, '/');
            var fileValSplit = fileVal.split("/");
            $(obj).next().children(0).val(fileValSplit[fileValSplit.length - 1]);
        }
    },

    /**
     * 값을 검사하여 각 단위에 맞게 변환해준다.
     * @param bytes bytes값
     */
    transformateUnit:function(bytes) {
        bytes = parseInt(bytes);
        var s = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
        var e = Math.floor(Math.log(bytes) / Math.log(1024));
        if (e == "-Infinity") return "0 " + s[0];
        else return (bytes / Math.pow(1024, Math.floor(e))).toFixed(2) + " " + s[e];
    }
};

var Caleandar = {
    caleandarImg:'/images/ico_calendar.gif',
    dateFormat:'yy-mm-dd',

    /**
     * var config = {
     *      targetId:'startDate',                           required
     *      btnImage:'/images/kwac/common/calendar.ico',    optional
     *      dateFormat:'yy-mm-dd'                           optional
     * }
     * Caleandar.createImageCalendar(config);
     *
     * dateFormat종류 몇가지 예)
     * (mm/dd/yy), (yy-mm-dd), (d M, y),
     * (d MM, y), (DD, d MM, yy), ('day' d 'of' MM 'in the year' yy)
     * @param config
     */
    createImageCalendar:function(config) {
        $('#' + config.targetId).datepicker({
            showOn: "button",
            buttonImage: config.btnImage || Caleandar.caleandarImg,
            buttonImageOnly: true,
            dateFormat:config.dateFormat || Caleandar.dateFormat
        });

        $('#' + config.targetId).after('&nbsp;');

        $('#' + config.targetId).bind('click',function(){
            $(this).next().click();
        });
    }
};

String.prototype.trim = function(chars) {
    if (chars) {
        var str = "[" + chars + "\\s]+";
        return this.replace(new RegExp(str, "g"), "");
    }

    return this.replace(/^\s+|\s+$/g, "");

}
String.prototype.ltrim = function(chars) {
    if (chars) {
        var str = "^[" + chars + "\\s]+";
        return this.replace(new RegExp(str, "g"), "");
    }

    return this.replace(/^\s+/, "");
}
String.prototype.rtrim = function(chars) {
    if (chars) {
        var str = "[" + chars + "\\s]+$";
        return this.replace(new RegExp(str, "g"), "");
    }

    return this.replace(/\s+$/, "");
}